package tech.mhuang.pacebox.core.compress.handler;

import tech.mhuang.pacebox.core.compress.CmdCompressHandler;
import tech.mhuang.pacebox.core.file.FileUtil;
import tech.mhuang.pacebox.core.util.ExecuteCmdUtil;

import java.io.File;
import java.io.IOException;

/**
 * 命令实现的RAR压缩解压类
 *
 * @author yuanhang.huang
 * @since 1.0.9
 */
public class RarCmdCompressHandler implements CmdCompressHandler {

    /**
     * 后缀标识
     */
    public static final String SUFFIX = ".rar";

    /**
     * code标识
     */
    public static final String CODE = "RAR";

    /**
     * 压缩命令
     */
    private static final String CMD_RAR = "rar";

    /**
     * 解压命令
     */
    private static final String CMD_UNRAR = "unrar";

    /**
     * RAR程序所在的目录
     */
    private String rarCmdDir = null;

    @Override
    public String getCmdDir() {
        return rarCmdDir;
    }

    @Override
    public void setCmdDir(String cmdDir) {
        this.rarCmdDir = cmdDir.endsWith(File.separator) ? cmdDir : cmdDir.concat(File.separator);
    }

    @Override
    public boolean match(String fileName) {
        return fileName.endsWith(SUFFIX);
    }

    @Override
    public void compress(String sourcePath, String destFile, boolean cover) throws IOException, InterruptedException {
        rarCmd(sourcePath, destFile, cover);
    }

    @Override
    public void decompress(String sourceFile, String destDir, boolean cover, boolean deep) throws IOException, InterruptedException {
        unRarCmd(sourceFile, destDir, cover, deep);
    }

    /**
     * 用linux命令压缩
     *
     * @param sourcePath 源文件/文件夹路径
     * @param destFile   压缩目标文件名
     * @param cover      是否覆盖
     * @throws IOException IOException
     * @throws InterruptedException InterruptedException
     */
    public void rarCmd(String sourcePath, String destFile, boolean cover) throws IOException, InterruptedException {
        String cmd = buildRarCmd(sourcePath, destFile, cover);
        if (rarCmdDir != null) {
            cmd = rarCmdDir.concat(cmd);
        }
        doCmd(cmd);
    }

    /**
     * 用linux命令解压
     *
     * @param sourceFile 源文件
     * @param destDir    解压目录
     * @param cover      是否覆盖
     * @param deep       是否深度递归解压
     * @throws IOException  IOException
     * @throws InterruptedException InterruptedException
     */
    public void unRarCmd(String sourceFile, String destDir, boolean cover, boolean deep) throws IOException, InterruptedException {
        String cmd = buildUnRarCmd(sourceFile, destDir, cover, deep);
        File dir = new File(destDir);
        if (!dir.exists()) {
            FileUtil.createDirectory(dir, true);
        }
        if (rarCmdDir != null) {
            cmd = rarCmdDir.concat(cmd);
        }
        doCmd(cmd);
    }

    /**
     * 生成压缩RAR的命令
     *
     * @param sourcePath 源文件/文件夹路径
     * @param destFile   压缩目标文件名
     * @param cover      是否覆盖
     * @return 命令
     */
    public String buildRarCmd(String sourcePath, String destFile, boolean cover) {
        StringBuffer cmd = new StringBuffer();
        cmd = cmd.append(CMD_RAR);
        cmd.append(" a -ep1");
        cmd = cover ? cmd.append(" -o+") : cmd.append(" -o-");
        cmd.append(" ").append(destFile).append(" ").append(sourcePath);
        return cmd.toString();
    }

    /**
     * 生成解压RAR的命令
     *
     * @param sourceFile 源文件
     * @param destDir    解压目录
     * @param cover      是否覆盖
     * @param deep       是否深度递归解压
     * @return 命令
     */
    public String buildUnRarCmd(String sourceFile, String destDir, boolean cover, boolean deep) {
        StringBuffer cmd = new StringBuffer();
        cmd = cmd.append(CMD_UNRAR);
        cmd.append(" x");
        if (deep) {
            cmd.append(" -r");
        }
        cmd = cover ? cmd.append(" -o+") : cmd.append(" -o-");
        cmd.append(" ").append(sourceFile).append(" ").append(destDir);
        return cmd.toString();
    }

    /**
     * 执行命令
     *
     * @param cmd 命令
     * @return 成功或失败
     * @throws IOException IOException
     * @throws InterruptedException InterruptedException
     */
    public boolean doCmd(String cmd) throws IOException, InterruptedException {
        return ExecuteCmdUtil.executeCmdSingle(cmd);
    }

}
